package cn.net.autocode.platform.file;

import cn.hutool.core.util.StrUtil;
import cn.net.autocode.core.bean.ResultT;
import cn.net.autocode.dbManager.Dao;
import cn.net.autocode.dbManager.SqlWrapperBuilder;
import cn.net.autocode.platform.config.SpringProfileConfig;
import cn.net.autocode.platform.file.service.FileHandle;
import cn.net.autocode.platform.file.service.FileServ;
import cn.net.autocode.platform.file.viewTemplate.*;
import cn.net.autocode.platform.viewEngine.AutoCodeThymeleaf;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.tika.detect.AutoDetectReader;
import org.apache.tika.exception.TikaException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Controller
@RequestMapping("autocode/fileProvider")
public class FileProviderCtrl{

    private final Dao dao;

    private final FileServ fileServ;

    private final SpringProfileConfig springProfileConfig;

    public FileProviderCtrl(Dao dao, FileServ fileServ, SpringProfileConfig springProfileConfig) {
        this.dao = dao;
        this.fileServ = fileServ;
        this.springProfileConfig = springProfileConfig;
    }

    @RequestMapping("upLoad")
    @Transactional
    @ResponseBody
    public ResultT upLoad(@RequestParam MultipartFile[] file, HttpServletRequest request) throws IOException {
        //获取参数信息
        Map<String,String[]> paramMap = request.getParameterMap();
        JSONObject param = new JSONObject();
        for(Map.Entry<String,String[]> entry:paramMap.entrySet()){
           String[] values = entry.getValue();
           if(values.length==1){
               param.put(entry.getKey(), values[0]);
           }else if(values.length>1){
               param.put(entry.getKey(), values);
           }
        }

        if(!param.containsKey("tableName")||!param.containsKey("busiId")){
            return  ResultT.fail("busiId、tableName两个参数不能为空！");
        }

        String busiId = param.getString("busiId");
        String tableName = param.getString("tableName");
        if(StrUtil.isBlank(busiId)||StrUtil.isBlank(tableName)||tableName.equals("undefined")||busiId.equals("undefined")){
            return  ResultT.fail("busiId、tableName两个参数不能为空！");
        }else{
            busiId = busiId.trim();
            tableName = tableName.trim();
        }


        //获取文件信息
        if (file==null||file.length==0){
            return  ResultT.fail("请选择需要上传的文件信息！");
        }

        //判定关联字段还是关联表
        String tableColumn = param.getString("tableColumn");
        if(StrUtil.isNotBlank(tableColumn)&&file.length>1){
            return  ResultT.fail("只能选择一个附件！");
        }

        //判定关联字段还是关联表
        String fileId = param.getString("fileId");
        if(StrUtil.isNotBlank(fileId)&&file.length>1){
            return  ResultT.fail("重新上传只能选择一个附件！");
        }

        if(StrUtil.isNotBlank(tableColumn)){
            //删除文件
            SqlWrapperBuilder swb = new SqlWrapperBuilder(tableName);
            swb.selectColumn(tableColumn);
            swb.eq("id",param.getString("busiId"));
            String oldFileId = dao.queryValue(swb.sqlWrapper().getSql(), String.class, swb.sqlWrapper().getParams().toArray());
            if(StrUtil.isNotBlank(oldFileId)){
                fileServ.delFile(oldFileId);
                dao.executeUpdate("update "+tableName+" set "+tableColumn+"=? where id=?",null,busiId);
            }
            //上传新的文件
            JSONObject fj = fileServ.saveFile(file[0],tableName,tableColumn,busiId,param.getString("attachmentType"));
            dao.executeUpdate("update "+tableName+" set "+tableColumn+"=? where id=?",fj.getString("id"),busiId);
            return ResultT.success(fj);
        }else{
            if(StrUtil.isNotBlank(fileId)){
                JSONObject fj = fileServ.updateFile(file[0],fileId);
                return ResultT.success(fj);
            }else{
                JSONArray fileAttr = new JSONArray();
                for (MultipartFile f : file) {
                    JSONObject fj = fileServ.saveFile(f,tableName,tableColumn,busiId,param.getString("attachmentType"));
                    fileAttr.add(fj);
                }
                return ResultT.success(fileAttr);
            }
        }
    }

    @RequestMapping("downLoad/{fileId}")
    @ResponseBody
    public ResponseEntity<byte[]> downLoad(@PathVariable(name="fileId") String fileId) {

        JSONObject file = dao.queryJSON("select * from autocode_file where id=?",fileId);
        if (file == null || file.isEmpty()) {
            throw new RuntimeException("文件不存在！");
        }
        String storage = file.getString("storage");
        byte[] bytes;
        if("database".equals(storage)){
            bytes = dao.readFile(fileId);
        }else{
            String path = file.getString("filePath");
            bytes = FileHandle.readFile(springProfileConfig.getRootDir(),path);
        }

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.add("file-name",URLEncoder.encode(file.getString("fileName"), StandardCharsets.UTF_8));
        headers.setContentDispositionFormData("attachment", URLEncoder.encode(file.getString("fileName"), StandardCharsets.UTF_8));
        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    }

    @RequestMapping("deleteFile/{fileId}")
    @Transactional
    @ResponseBody
    public ResultT deleteFile(@PathVariable(name="fileId") String fileId) throws IOException {
        fileServ.delFile(fileId);
        return ResultT.success();
    }

    @RequestMapping("batchDeleteFile")
    @Transactional
    @ResponseBody
    public ResultT batchDeleteFile(@RequestBody JSONArray fileIds) throws IOException {
        for(int i=0;i<fileIds.size();i++){
            fileServ.delFile(fileIds.getString(i));
        }
        return ResultT.success();
    }

    @RequestMapping("image/{fileId}")
    @ResponseBody
    public ResponseEntity<byte[]> image(@PathVariable("fileId") String fileId) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        byte[] bytes = new byte[0];
        if(fileId!=null && !"undefined".equals(fileId) && !"null".equals(fileId)){
            JSONObject file = dao.queryJSON("select * from autocode_file where id=?",fileId);
            if (file != null && !file.isEmpty()) {
                String storage = file.getString("storage");
                if("database".equals(storage)){
                    bytes = dao.readFile(fileId);
                }else{
                    String path = file.getString("filePath");
                    bytes = FileHandle.readFile(springProfileConfig.getRootDir(),path);
                }
            }
        }
        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    }

    @RequestMapping("filePreview/{fileId}")
    public ModelAndView filePreview(@PathVariable("fileId") String fileId) {
        ModelAndView mav = new ModelAndView();
        JSONObject att = dao.queryJSON("select * from autocode_file where id=?",fileId);

        try {
            String html;
            String fileType = att.getString("fileType").toLowerCase();
            String fileName = att.getString("fileName");
            System.out.println(fileType);
            if(fileType.equals("pdf")){
                String contentUrl = "/autocode/fileProvider/previewContent/"+fileId;
                html= PdfView.template.replace("{fileId}",fileId).replace("{fileName}",fileName).replace("{contentUrl}",contentUrl);
            }else if(fileType.equals("doc")||fileType.equals("docx")){
                String contentUrl = "/autocode/fileProvider/previewContent/"+fileId;
                html= WordView.template.replace("{fileId}",fileId).replace("{fileName}",fileName).replace("{contentUrl}",contentUrl);
            }else if(fileType.equals("xlsx")||fileType.equals("xls")){
                html= ExcelView.template.replace("{fileId}",fileId).replace("{fileName}",fileName);
            }else if(fileType.equals("png")||fileType.equals("jpg")||fileType.equals("jpeg")){
                html= ImageView.template.replace("{fileId}",fileId).replace("{fileName}",fileName);
            }else if(fileType.equals("txt")){
                //获取文件内容
                String storage = att.getString("storage");
                byte[] bytes;
                if("database".equals(storage)){
                    bytes = dao.readFile(fileId);
                }else{
                    String path = att.getString("filePath");
                    bytes = FileHandle.readFile(springProfileConfig.getRootDir(),path);
                }

                InputStream inputStream = new ByteArrayInputStream(bytes);
                AutoDetectReader reader = new AutoDetectReader(inputStream);
                // 获取检测到的编码
                Charset charset = reader.getCharset();
                String content = new String(bytes,charset);
                mav.addObject("fileData",content);
                mav.addObject("fileName",fileName);
                html= TxtView.template.replace("{fileId}",fileId).replace("{fileNameTitle}",fileName);
            }else{
                html = OtherView.template.replace("{fileId}",fileId).replace("{fileName}",fileName);;
            }
            View view = new AutoCodeThymeleaf(html);
            mav.setView(view);
            return mav;
        } catch (IOException | TikaException e) {
            throw new RuntimeException(e);
        }
    }


    @RequestMapping(value = "previewContent/{fileId}")
    public void previewContent(@PathVariable("fileId") String fileId, HttpServletResponse response) throws IOException {
        JSONObject file = dao.queryJSON("select * from autocode_file where id=?",fileId);
        String storage = file.getString("storage");
        byte[] fileBytes;
        if("database".equals(storage)){
            fileBytes = dao.readFile(fileId);
        }else{
            String path = file.getString("filePath");
            fileBytes = FileHandle.readFile(springProfileConfig.getRootDir(),path);
        }

        //获取响应输出流
        ServletOutputStream os = response.getOutputStream();
        String fileName = file.getString("fileName");
        response.setHeader("content-disposition","inline;fileName=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
        os.write(fileBytes);
        os.flush();
        os.close();
    }

}
